package com.gofaraway.common.util.lambda;

import org.apache.commons.lang3.StringUtils;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.*;
import java.util.stream.Collectors;

/**
 * @author ChenPeng
 * @Date 2024/1/18 17:46
 */
public class LambdaUtil {


    /**
     * 根据传递过来的并发map 去重
     *
     * @param key
     * @param map
     * @param <T>
     * @return
     */
    public static <T> boolean distinctByKey(T key, ConcurrentHashMap<T, Boolean> map) {

        return map.putIfAbsent(key,Boolean.TRUE) == null;
    }


    /**
     * 根据多个值去重
     *
     * @param keyExtractors
     * @param <T>
     * @return
     */
    public static <T> Predicate<T> distinctByKeys(Function<? super T, ?>... keyExtractors) {
        final ConcurrentHashMap<List<?>, Boolean> seen = new ConcurrentHashMap<>();

        return t -> {
            final List<?> keys = Arrays.stream(keyExtractors)
                    .map(ke -> ke.apply(t))
                    .collect(Collectors.toList());
            return seen.putIfAbsent(keys, Boolean.TRUE) == null;
        };
    }

    /**
     * 过滤
     *
     * @param from
     * @param predicate
     * @param <T>
     * @return
     */
    public static <T> List<T> filterList(Collection<T> from, Predicate<T> predicate) {
        if (isEmpty(from)) {
            return new ArrayList<>();
        }
        return from.stream().filter(predicate).collect(Collectors.toList());
    }

    /**
     * 转换 list
     *
     * @param from
     * @param func
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T,U> List<U> convertList(Collection<T> from,Function<T, U> func) {
        if (isEmpty(from)) {
            return new ArrayList<>();
        }
        return from.stream().map(func).collect(Collectors.toList());
    }

    /**
     * 转换list
     *
     * @param from
     * @param func
     * @param consumer
     * @return java.util.List<U>
     * @Author: LiYuhang
     * @Date 2022/1/13 16:24
     */
    public static <T,U> List<U> convertList(@NotNull Collection<T> from, @NotNull Function<T, U> func, @NotNull Consumer<U> consumer) {
        if (isEmpty(from)) {
            return new ArrayList<>();
        }
        return from.stream().map(func).peek(consumer).collect(Collectors.toList());
    }
    /**
     * 转换set
     *
     * @param from
     * @param func
     * @param <T>
     * @param <U>
     * @return
     */
    public static <T,U> Set<U> convertSet(Collection<T> from, Function<T, U> func) {
        if (isEmpty(from)) {
            return new HashSet<>();
        }
        return from.stream().map(func).collect(Collectors.toSet());
    }

    /**
     * 转换map
     *
     * @param from    list
     * @param keyFunc
     * @param <T>     map key
     * @param <K>     map value
     * @return
     */
    public static <T,K> Map<K, T> convertMap(Collection<T> from,Function<T, K> keyFunc) {
        if (isEmpty(from)) {
            return new HashMap<>();
        }
        return convertMap(from,keyFunc,Function.identity());
    }

    /**
     * @param from     list
     * @param keyFunc  key
     * @param supplier
     * @param <T>
     * @param <K>
     * @return
     */
    public static <T,K,M extends Map<K, T>> M convertMap(Collection<T> from, Function<T, K> keyFunc, Supplier<M> supplier) {
        if (isEmpty(from)) {
            return supplier.get();
        }
        return convertMap(from,keyFunc,Function.identity(),supplier);
    }

    /**
     * @param from      集合
     * @param keyFunc   key
     * @param valueFunc value
     * @param <T>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <T,K,V> Map<K, V> convertMap(Collection<T> from,Function<T, K> keyFunc,Function<T, V> valueFunc) {
        if (isEmpty(from)) {
            return new HashMap<>();
        }
        return convertMap(from,keyFunc,valueFunc,(v1,v2) -> v1);
    }

    /**
     * @param from          list
     * @param keyFunc       key
     * @param valueFunc     value
     * @param mergeFunction 冲突合并
     * @param <T>
     * @param <K>
     * @param <V>
     * @return
     */
    public static <T,K,V> Map<K, V> convertMap(Collection<T> from,
                                               Function<T, K> keyFunc,
                                               Function<T, V> valueFunc,
                                               BinaryOperator<V> mergeFunction) {
        if (isEmpty(from)) {
            return new HashMap<>();
        }
        return convertMap(from,keyFunc,valueFunc,mergeFunction,HashMap::new);
    }

    public static <T,K,V,M extends Map<K, V>> M convertMap(Collection<T> from,
                                                           Function<T, K> keyFunc,
                                                           Function<T, V> valueFunc,
                                                           Supplier<M> supplier) {
        if (isEmpty(from)) {
            return supplier.get();
        }
        return convertMap(from,keyFunc,valueFunc,(v1,v2) -> v1,supplier);
    }

    /**
     * @param from          list
     * @param keyFunc       key
     * @param valueFunc     value
     * @param mergeFunction key冲突合并
     * @param supplier      待返回容器
     * @param <T>
     * @param <K>
     * @param <V>
     * @param <M>
     * @return
     */
    public static <T,K,V,M extends Map<K, V>> M convertMap(Collection<T> from,
                                                           Function<T, K> keyFunc,
                                                           Function<T, V> valueFunc,
                                                           BinaryOperator<V> mergeFunction,
                                                           Supplier<M> supplier) {
        if (isEmpty(from)) {
            return supplier.get();
        }

        return from.stream().collect(Collectors.toMap(keyFunc,valueFunc,mergeFunction,supplier));
    }


    /**
     * 如果 t 不为null 则 执行
     *
     * @param t
     * @param consumer
     * @param <T>
     */
    public static <T> void notNullAndThen(T t,Consumer<T> consumer) {
        Optional.ofNullable(t).ifPresent(consumer);
    }

    /**
     * 如果 str 不是空字符串，则执行 Consumer
     *
     * @param str
     * @param consumer
     */
    public static void ifNotEmptyAndThen(String str,Consumer<String> consumer) {
        if (StringUtils.isNotBlank(str)) {
            consumer.accept(str);
        }
    }

    public static void ifEmptyAndThen(String str,Consumer<String> consumer) {
        if (StringUtils.isBlank(str)) {
            consumer.accept(str);
        }
    }

    /**
     * 多线程阻塞1
     *
     * @param futures
     */
    public static void allFutureJoin(CompletableFuture... futures) {

        Arrays.asList(futures).forEach(CompletableFuture::join);
    }

    /**
     * 多线程阻塞2
     *
     * @param futures
     */
    public static void futureListJoin(CompletableFuture... futures) {
        CompletableFuture.allOf(futures).join();
    }

    /**
     * 多线程阻塞3
     *
     * @param futureList
     */
    public static void futureListJoin(List<CompletableFuture> futureList) {
        futureList.forEach(CompletableFuture::join);
    }

    /********************************************************************************************************************/

    private static boolean isEmpty(Collection coll) {
        return coll == null || coll.isEmpty();
    }


}
